package com.example.graphmovieapp.domain.entity;

import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Property;
import org.springframework.data.neo4j.core.schema.Relationship;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import com.alibaba.fastjson2.annotation.JSONField;

import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Max;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Person实体类，表示图数据库中的人物节点
 * 
 * @author GraphMovieApp
 * @version 1.0
 */
@Node("Person")
public class Person {
    
    /**
     * 人物ID，主键
     */
    @Id
    @GeneratedValue
    private Long id;
    
    /**
     * 人物姓名
     */
    @Property("name")
    @NotBlank(message = "人物姓名不能为空")
    private String name;
    
    /**
     * 出生年份
     */
    @Property("born")
    @Min(value = 1800, message = "出生年份不能早于1800年")
    @Max(value = 2100, message = "出生年份不能晚于2100年")
    private Integer born;
    
    /**
     * 参演的电影列表（ACTED_IN关系）
     */
    @Relationship(type = "ACTED_IN", direction = Relationship.Direction.OUTGOING)
    @JSONField(serialize = false, deserialize = false)
    private List<Movie> actedInMovies = new ArrayList<>();

    /**
     * 执导的电影列表（DIRECTED关系）
     */
    @Relationship(type = "DIRECTED", direction = Relationship.Direction.OUTGOING)
    @JSONField(serialize = false, deserialize = false)
    private List<Movie> directedMovies = new ArrayList<>();
    
    /**
     * 默认构造函数
     */
    public Person() {
    }
    
    /**
     * 带参数的构造函数
     * 
     * @param name 人物姓名
     * @param born 出生年份
     */
    public Person(String name, Integer born) {
        this.name = name;
        this.born = born;
    }
    
    /**
     * 获取人物ID
     * 
     * @return 人物ID
     */
    public Long getId() {
        return id;
    }
    
    /**
     * 设置人物ID
     * 
     * @param id 人物ID
     */
    public void setId(Long id) {
        this.id = id;
    }
    
    /**
     * 获取人物姓名
     * 
     * @return 人物姓名
     */
    public String getName() {
        return name;
    }
    
    /**
     * 设置人物姓名
     * 
     * @param name 人物姓名
     */
    public void setName(String name) {
        this.name = name;
    }
    
    /**
     * 获取出生年份
     * 
     * @return 出生年份
     */
    public Integer getBorn() {
        return born;
    }
    
    /**
     * 设置出生年份
     * 
     * @param born 出生年份
     */
    public void setBorn(Integer born) {
        this.born = born;
    }
    
    /**
     * 获取参演的电影列表
     * 
     * @return 参演的电影列表
     */
    public List<Movie> getActedInMovies() {
        return actedInMovies;
    }
    
    /**
     * 设置参演的电影列表
     * 
     * @param actedInMovies 参演的电影列表
     */
    public void setActedInMovies(List<Movie> actedInMovies) {
        this.actedInMovies = actedInMovies;
    }
    
    /**
     * 获取执导的电影列表
     * 
     * @return 执导的电影列表
     */
    public List<Movie> getDirectedMovies() {
        return directedMovies;
    }
    
    /**
     * 设置执导的电影列表
     * 
     * @param directedMovies 执导的电影列表
     */
    public void setDirectedMovies(List<Movie> directedMovies) {
        this.directedMovies = directedMovies;
    }
    
    /**
     * 添加参演的电影
     * 
     * @param movie 参演的电影
     */
    public void addActedInMovie(Movie movie) {
        if (!actedInMovies.contains(movie)) {
            actedInMovies.add(movie);
        }
    }
    
    /**
     * 移除参演的电影
     * 
     * @param movie 参演的电影
     */
    public void removeActedInMovie(Movie movie) {
        actedInMovies.remove(movie);
    }
    
    /**
     * 添加执导的电影
     * 
     * @param movie 执导的电影
     */
    public void addDirectedMovie(Movie movie) {
        if (!directedMovies.contains(movie)) {
            directedMovies.add(movie);
        }
    }
    
    /**
     * 移除执导的电影
     * 
     * @param movie 执导的电影
     */
    public void removeDirectedMovie(Movie movie) {
        directedMovies.remove(movie);
    }
    
    /**
     * 重写equals方法
     * 
     * @param o 比较对象
     * @return 是否相等
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return Objects.equals(id, person.id) && 
               Objects.equals(name, person.name) && 
               Objects.equals(born, person.born);
    }
    
    /**
     * 重写hashCode方法
     * 
     * @return 哈希值
     */
    @Override
    public int hashCode() {
        return Objects.hash(id, name, born);
    }
    
    /**
     * 重写toString方法
     * 
     * @return 字符串表示
     */
    @Override
    public String toString() {
        return "Person{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", born=" + born +
                '}';
    }
}